package com.txh.blog.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.txh.blog.consts.Consts;
import com.txh.blog.dto.ArticleLabelDto;
import com.txh.blog.mapper.ArticleMapper;
import com.txh.blog.mapper.LabelMapper;
import com.txh.blog.mapper.LinkMapper;
import com.txh.blog.mapper.TypeMapper;
import com.txh.blog.model.Article;
import com.txh.blog.model.Label;
import com.txh.blog.model.Link;
import com.txh.blog.model.Type;
import com.txh.blog.model.extend.ArticleExtend;
import com.txh.blog.mq.MqSend;
import com.txh.blog.service.ArticleService;
import com.txh.blog.service.LabelService;
import com.txh.blog.service.LinkService;
import com.txh.blog.service.RedisService;
import com.txh.blog.util.OssCliectUtils;
import com.txh.blog.vo.ArticelVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

@Service
@Transactional
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private LabelMapper labelMapper;
    @Autowired
    private TypeMapper typeMapper;
    @Autowired
    private RedisService redisService;
    @Autowired
    private LabelService labelService;
    @Autowired
    private LinkMapper linkMapper;
    @Autowired
    private MqSend mqSend;

    @Override
    public List<ArticelVo> partArticelList() {
        return articleMapper.partArticel();
    }

    @Override
    @Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
    public Map<String, Object> articlePages(Map<String,Object> param,Integer statu) {
        Map<String,Object> pageInfo = new HashMap<>();
        String num =(String)param.get("pageNum");
        String size= (String) param.get("pageSize");
        Integer pageNum = num==null?1:Integer.valueOf(num);
        Integer pageSize =size ==null?10:Integer.valueOf(size);
        String keyWords = (String)param.get("keyWords");
        String type =(String)param.get("type");
        Integer total=0;
        List<ArticleExtend> articles=null;
        if (type == null || type .equals("")){
            total = articleMapper.countArticle(keyWords,statu);
            articles= articleMapper.selectAllByCondtion((pageNum-1)*pageSize,pageSize,keyWords,statu);

        }else if(type.equals("label")){
            Long labelId = Long.valueOf((String) param.get("labelId"));
            total = articleMapper.articleOfLabelById(labelId,statu);
            articles = articleMapper.articleOfLabels((pageNum-1)*pageSize,pageSize,labelId,statu);
        }else if (type.equals("type")){
            Long typeId = Long.parseLong((String) param.get("typeId"));
            total = articleMapper.articleOfTypeById(typeId,statu);
            articles= articleMapper.articlesOfTypeId((pageNum-1)*pageSize,pageSize,typeId,statu);
        }
        //获取标签
        List<Label> labels =null;
        if (redisService.hasKey(Consts.LABELS_CACHE)){
            labels= (List<Label>) JSONObject.parse((String)redisService.get(Consts.LABELS_CACHE));
        }else{
            labels=labelService.allLabels();
        }
        //按照阅读量降序排列数据缓存一个小时
        List<Article> rankings=null;
        if (redisService.hasKey(Consts.RANKINGS_ATRICLES)){
            rankings= (List<Article>) JSONObject.parse((String)redisService.get(Consts.RANKINGS_ATRICLES));
        }else{
            rankings=rankingsArticle();
        }
        //友链
        List<Link> links=null;
        if (redisService.hasKey(Consts.FRIEND_LINK)){
            links=(List<Link>)JSONObject.parse((String)redisService.get(Consts.FRIEND_LINK));
        }else{
            links=links();
        }
        pageInfo.put("total",total);
        pageInfo.put("list",articles);
        pageInfo.put("curr",pageNum);
        pageInfo.put("keyWords",keyWords);
        pageInfo.put("labels",labels);
        pageInfo.put("rankings",rankings);
        pageInfo.put("links",links);
        return pageInfo;
    }
    private List<Article> rankingsArticle(){
        List<Article> rankings = articleMapper.rankingsArticles();
        redisService.set(Consts.RANKINGS_ATRICLES,JSONObject.toJSONString(rankings),100);
        return rankings;
    }

    private List<Link> links(){
        List<Link> links = linkMapper.selectAll();
        redisService.set(Consts.FRIEND_LINK,JSONObject.toJSONString(links),100);
        return links;
    }

    @Override
    public void deleteAtrilceById(Long param) {
        articleMapper.deleteByPrimaryKey(param);
        labelMapper.deleteByArticleId(param);
    }

    @Override
    public ArticelVo editArticleById(Long id) {
        ArticelVo articelVo = articleMapper.selectArticleById(id);
        articelVo.setLabels(labelMapper.selectArticleLabelListByArticelId(id));
        return articelVo;
    }

    @Override
    public Map<String, Object> getLablesAndTypes() {
        Map<String,Object> map = new HashMap<>();
        List<Label> labels = labelMapper.selectAll();
        List<Type> types = typeMapper.selectAll();
        map.put("labels",labels);
        map.put("types",types);
        return map;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void addArticle(Article article,String labels) {
        //判断是否存在id
        if(article.getId() == null){
            article.setReadNum(0);
            article.setCreateTime(new Date());
            articleMapper.insert(article);
            List<ArticleLabelDto> articleLabelDtos = articleLabelDtos(labels,article.getId());
            articleMapper.insertArticleLabel(articleLabelDtos);
        }else{
            article.setReadNum(0);
            article.setCreateTime(new Date());
            articleMapper.updateByPrimaryKey(article);
            //先删除标签
            labelMapper.deleteByArticleId(article.getId());
            //从添加标签
            List<ArticleLabelDto> articleLabelDtos = articleLabelDtos(labels,article.getId());
            articleMapper.insertArticleLabel(articleLabelDtos);
        }
    }

    @Override
    public void publishArticle(Long id, Integer statu) {
        articleMapper.updateArticleStatuById(id,statu);
    }

    @Override
    public JSONObject uploadFile(MultipartFile file) {
        JSONObject jsonObject = new JSONObject();
        try {
            InputStream fileInputStream =  file.getInputStream();
            String url = OssCliectUtils.uploadByInputStream(file.getInputStream(),file.getName());
            String [] reslutPath = new String[]{url};
            jsonObject.put("errno",0);
            jsonObject.put("data",reslutPath);
        } catch (IOException e) {
            e.printStackTrace();
            jsonObject.put("errno",1);
            jsonObject.put("data",null);
        }
        return jsonObject;
    }

    @Override
    public Map<String, Object> getArticleInfoById(Long id) {
        Map<String,Object> info = new HashMap<>();
        mqSend.sendMessage(id);
        ArticleExtend article = articleMapper.findArticleById(id);
        //获取标签
        List<Label> labels =null;
        if (redisService.hasKey(Consts.LABELS_CACHE)){
            labels= (List<Label>) JSONObject.parse((String)redisService.get(Consts.LABELS_CACHE));
        }else{
            labels=labelService.allLabels();
        }
        //按照阅读量降序排列数据缓存一个小时
        List<Article> rankings=null;
        if (redisService.hasKey(Consts.RANKINGS_ATRICLES)){
            rankings= (List<Article>) JSONObject.parse((String)redisService.get(Consts.RANKINGS_ATRICLES));
        }else{
            rankings=rankingsArticle();
        }
        List<Link> links = null;
        if (redisService.hasKey(Consts.FRIEND_LINK)){
            links = (List<Link>)JSONObject.parse((String) redisService.get(Consts.FRIEND_LINK));
        }else{
            links=links();
        }
        info.put("article",article);
        info.put("labels",labels);
        info.put("rankings",rankings);
        info.put("links",links);
        return info;
    }

    @Override
    public void incrReadNumById(Long id) {
        articleMapper.incrReadNum(id);
    }

    private List<ArticleLabelDto> articleLabelDtos(String lables,Long artId){
        //获取标签
        String [] labelArray = lables.split(",");
        List<ArticleLabelDto> articleLabelDtos = new ArrayList<>();
        for (int i=0;i<labelArray.length;i++){
            ArticleLabelDto articleLabelDto = new ArticleLabelDto();
            articleLabelDto.setArticleId(artId);
            articleLabelDto.setLabelId(Long.valueOf(labelArray[i]));
            articleLabelDtos.add(articleLabelDto);
        }
        return articleLabelDtos;
    }

}
